package com.example.seckill.Controller;

import com.example.seckill.Exception.ErrorEnum;
import com.example.seckill.Exception.GlobalException;
import com.example.seckill.Util.JsonUtil;
import com.example.seckill.Util.MD5Util;
import com.example.seckill.VO.OrderRequest;

import com.example.seckill.VO.RoomVO;

import com.example.seckill.VO.Student_Bed_Order_VO;

import com.example.seckill.annotation.CurrentUser;
//import com.example.seckill.annotation.RoleLimit;
import com.example.seckill.common.CommonResult;
import com.example.seckill.common.RabbitMQ.MQSender;
import com.example.seckill.mapper.OrderMapper;
import com.example.seckill.mapper.RoomMapper;

import com.example.seckill.pojo.Student_Bed_Order;
import com.example.seckill.pojo.User;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/order")
public class OrderController
        implements InitializingBean
{
    @Autowired

    OrderMapper orderMapper;
    @Autowired

    RoomMapper roomMapper;

    @Autowired

    RedisTemplate redisTemplate;

    @Autowired
    MQSender mqSender;

    //内存标记，减少对redis访问
    private  Map<String,Boolean> EmptyStockMap=new HashMap<>();

    @PostMapping ("{path}/book")
    public  CommonResult Book(@CurrentUser User user, @RequestBody RoomVO roomVO,@PathVariable String path)  {
        System.out.println("预订");
        // 判断信息信息是否完善
        if(user.getName()==null||user.getGender()==null) throw new GlobalException(ErrorEnum.INCOMPLETE_INFO);
        String rid=roomVO.getRoom_id();
        //检查路径是否正确
        if(rid==null||path.isEmpty())
            throw new GlobalException(ErrorEnum.REQUEST_ILLEGAL);

        String redisPath= (String) redisTemplate.opsForValue().get("seckillPath"+user.getUsername()+rid);
        if(!Objects.equals(redisPath, path)) throw new GlobalException(ErrorEnum.REQUEST_ILLEGAL);

        ValueOperations valueOperations=redisTemplate.opsForValue();


        //查找是否重复抢购
        Student_Bed_Order order=(Student_Bed_Order) redisTemplate.opsForValue().get("order:"+user.getUsername());

        if(order!=null) throw new GlobalException(ErrorEnum.REPEATE_ERROR);

        //检查性别是否一致
        Integer room_gender=(Integer) redisTemplate.opsForValue().get("room_gender:"+roomVO.getRoom_id());
        System.out.println("用户性别"+user.getGender());
        System.out.println("房间性别"+room_gender);
        if(!Objects.equals(user.getGender(), room_gender)) throw new GlobalException(ErrorEnum.GENDER_ILLEGAL);

        //内存标记
        if(EmptyStockMap.get(rid)) throw new GlobalException(ErrorEnum.EMPTY_STOCK);

        //预减库存
        Long stock=valueOperations.decrement("RoomInventory:"+rid);
        if(stock<0) {
            EmptyStockMap.put(rid,true);
            valueOperations.increment("RoomInventory:"+rid);
            throw new GlobalException(ErrorEnum.EMPTY_STOCK);
        }


        //下单
        OrderRequest newOrder=new OrderRequest();
        newOrder.setRoom_id(rid);
        newOrder.setStudent_id(user.getUsername());
        //进入消息队列
        //发送消息

        mqSender.sendOrderMessage(JsonUtil.object2JsonStr(newOrder));
        System.out.println("消息队列返回");
        //马上返回0，前端接收到0，显示“排队中”
        return CommonResult.success(0);


    }
    /*生成秒杀地址*/
//    @AccessLimit(seconds=5,maxCount=5)
    @GetMapping("/getPath/{room_id}")
    public CommonResult<String> getPath(@CurrentUser User user, @PathVariable String room_id,
//                                        @RequestParam String captcha,
                                        HttpServletRequest request){
        System.out.println("获取秒杀地址");

//        if(captcha==null) throw new GlobalException(ErrorEnum.ERROR_CAPTCHA);
        //限制访问次数
        ValueOperations valueOperations=redisTemplate.opsForValue();
        //限制次数，5秒内访问5次(计数器算法）
        String uri=request.getRequestURI();
        System.out.println("uri="+uri);
        Integer cnt=(Integer)valueOperations.get(uri+":"+user.getUsername());
        System.out.println(1);
        if(cnt==null) valueOperations.set(uri+":"+user.getUsername(),1,5,TimeUnit.SECONDS);
        else if(cnt<5) valueOperations.increment(uri+":"+user.getUsername());
        else {
            System.out.println("超过限制");
            throw new GlobalException(ErrorEnum.ACCESS_LIMIT_REACHED);
        }
//        System.out.println("cnt="+cnt);

         //检验captcha
//        boolean check=checkOrderCaptcha(captcha,user,room_id);

//        if(!check) throw new GlobalException(ErrorEnum.ERROR_CAPTCHA);
        //生成地址存在redis
        String str= user.getUsername()+ MD5Util.md5(user.getUsername()+"sspku");
        redisTemplate.opsForValue().set("seckillPath"+user.getUsername()+room_id,str
//                ,68, TimeUnit.SECONDS
        );
        return CommonResult.success(str);
    }
    public  boolean checkOrderCaptcha(String captcha, @CurrentUser User user, String room_id){
        if(captcha==null) return false;
        String redisCaptcha=(String) redisTemplate.opsForValue().get("captcha:"+user.getUsername()+":"+room_id);
        System.out.println("captcha="+captcha);
        System.out.println("rediscaptcha="+redisCaptcha);
        return captcha.equals(redisCaptcha);
    }

    /*
     **初始化预减库存，把库存预加载到redis中
     * */
    @Override
    public void afterPropertiesSet() throws Exception {
//        System.out.println("初始化");
//        if(roomMapper==null) return ;
//        System.out.println("roomMapper不为空");
//        if(redisTemplate==null) return;
//            System.out.println("redisTemplate不为空");
//        if(redisTemplate.opsForValue()==null) System.out.println("redis为空");
        List<RoomVO> roomVOList=roomMapper.getRoomList();
//
//        System.out.println(1);
//
        if(roomVOList==null) return ;
        System.out.println(roomVOList);

        roomVOList.forEach(roomVO -> {
            if(roomVO==null) System.out.println("roomVO为空");

//            System.out.println(roomVO.getRoom_id());
//            //预存库存
            redisTemplate.opsForValue().set("RoomInventory:"+roomVO.getRoom_id(), roomVO.getRoom_inventory());
            //预存性别
            redisTemplate.opsForValue().set("room_gender:"+roomVO.getRoom_id(),roomVO.getRoom_gender());
            //内存标记
            EmptyStockMap.put(roomVO.getRoom_id(),false);
//
        });
    }


       //测试
//        public static void main(String[] args) throws Exception {
//            if(roomMapper==null) System.out.println(roomMapper==null);
//            List<RoomVO> roomVOList = roomMapper.getRoomList();
//
//            System.out.println(1);
//
//            if (roomVOList == null) return;
////
//            roomVOList.forEach(roomVO -> {
//                //预存库存
//                redisTemplate.opsForValue().set("RoomInventory:" + roomVO.getRoom_id(), roomVO.getRoom_inventory());
//                //预存性别
//                redisTemplate.opsForValue().set("room_gender:" + roomVO.getRoom_id(), roomVO.getRoom_gender());
//                //内存标记
//                EmptyStockMap.put(roomVO.getRoom_id(), false);
////
//            });
//        }
    /*测试RabbitMQ*/
//    @GetMapping("/mq")
//    public void testMQ() throws InterruptedException {
//
//        for (int i = 0; i < 50; i++){
//        mqSender.send("hello,rabbit"+i);
//
//        }
//    }

    /**
     * 客户端轮询获得结果
     *@return : order_id":成功 -1:失败 0：排队中
     */
    @PostMapping("/getResult")
    public CommonResult getResult(@CurrentUser User user, @RequestBody RoomVO roomVO){
//        OrderVO order=new OrderVO();
//        order.setStudent_id(user.getUsername());
//        order.setRoom_id(roomVO.getRoom_id());
        System.out.println("查找订单");
//        Order foundOrder=orderMapper.checkOrder(user);
        Student_Bed_Order_VO foundOrder=orderMapper.getStudentBedOrder(user);
        //成功
        System.out.println("返回排队中");

        //System.out.println(JsonUtil.object2JsonStr(foundOrder));
        //不能这样打印，订单可能还没生成
//        if(foundOrder.getStudent_id()==null) System.out.println("stuid=null");
//        if(foundOrder.getRoom_id()==null) System.out.println("rid=null");
        if(foundOrder==null) return CommonResult.success(0);
        System.out.println("返回重复订购");
        if(!foundOrder.getRoom_id().equals(roomVO.getRoom_id())){
            System.out.println("rvo.rid:"+roomVO.getRoom_id());
            System.out.println("frd.rid:"+foundOrder.getRoom_id());
            throw new GlobalException(ErrorEnum.REPEATE_ERROR);
        }
        System.out.println("返回失败");
        if(redisTemplate.hasKey("isStockEmpty:"+roomVO.getRoom_id())) return CommonResult.success(-1);
        System.out.println("返回成功");
        return CommonResult.success(foundOrder);

        //如果没有库存

        //排队中

    }
    //    getOrderByUID
    @GetMapping("/getOrderByUID")
    public CommonResult getOrderList(@CurrentUser User user){
        Student_Bed_Order_VO foundOrder=orderMapper.getStudentBedOrder(user);

//        Order foundOrder=orderMapper.getOrderByUID(user.getUsername());
        //成功

        if(foundOrder==null) throw new GlobalException(ErrorEnum.NO_ORDER_FOUND);

        return CommonResult.success(foundOrder);


    }


    @GetMapping("/getOrderList")
    public CommonResult getOrderList(){
        List<Student_Bed_Order_VO> foundOrder=orderMapper.getOrderList();



        if(foundOrder.isEmpty()) throw new GlobalException(ErrorEnum.NO_ORDER_FOUND);

        return CommonResult.success(foundOrder);


    }

}